package com.alinesno.cloud.operation.cmdb.controller;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.ui.Model;

import com.alinesno.cloud.operation.cmdb.common.constants.AccountRoleEnum;
import com.alinesno.cloud.operation.cmdb.common.constants.OrderStatusEnum;
import com.alinesno.cloud.operation.cmdb.common.constants.RunConstants;
import com.alinesno.cloud.operation.cmdb.entity.BaseEntity;
import com.alinesno.cloud.operation.cmdb.entity.MasterMachineEntity;
import com.alinesno.cloud.operation.cmdb.entity.ResourceEntity;
import com.alinesno.cloud.operation.cmdb.repository.BaseJpaRepository;
import com.alinesno.cloud.operation.cmdb.repository.MasterMachineRepository;
import com.alinesno.cloud.operation.cmdb.service.AccountService;
import com.alinesno.cloud.operation.cmdb.third.data.QiniuUploadTool;
import com.alinesno.cloud.operation.cmdb.web.api.ApiParent;
import com.alinesno.cloud.operation.cmdb.web.bean.AccountBean;
import com.alinesno.cloud.operation.cmdb.web.bean.JqDatatablesPageBean;
import com.alinesno.cloud.operation.cmdb.web.bean.OrderInfoBean;

public class BaseController extends ApiParent {

	private static final Logger logger = LoggerFactory.getLogger(BaseController.class);

	public static final String WX_PAGE = "pages/";
	public static final String WX_MANAGER = "manager/";

	@Value("${excel.temp.dir}")
	protected String stackFileExport; // 输出路径
	
	@Autowired
	protected QiniuUploadTool qiniuUploadTool ; 

	@Autowired
	protected HttpServletRequest request;

	@Autowired
	protected AccountService accountService;

	@Autowired
	protected MasterMachineRepository masterMachineRepository;

	protected AccountBean currentManager() {
		Object currentManagerObj = request.getSession().getAttribute(RunConstants.CURRENT_MANAGER);
		if (currentManagerObj != null) {
			return (AccountBean) currentManagerObj;
		}
		return null;
	}
	
	@Override
	public Object handler(HttpServletRequest request, HttpServletResponse response) {
		return null;
	}

	protected void createMenus(Model model) {
		AccountBean account = currentManager();

		if (account != null) {
			List<ResourceEntity> list = accountService.findResourceByUserId(account.getId());
			model.addAttribute("menus", list);
		}

		// 列出机房
		List<MasterMachineEntity> school = null;
		if (AccountRoleEnum.ADMIN.getCode().equals(currentManager().getRolePower())) {
			school = masterMachineRepository.findAll();
		} else {
			school = masterMachineRepository.findAllByMasterCode(currentManager().getMasterCode());
		}
		logger.debug("school = {} , code = {}", school, currentManager().getMasterCode());
		model.addAttribute("schools", school);

	}

	/**
	 * 设置状态
	 * 
	 * @param bean
	 */
	public void setSendStatus(OrderInfoBean bean) {
		String status = bean.getSendStatus();
		bean.setSendStatusLabel(OrderStatusEnum.getStatus(status).getText());
	}

	/**
	 * Spring mvc 重定向
	 * 
	 * @param url
	 * @return
	 */
	public String redirect(String url) {
		return "redirect:" + url;
	}

	/**
	 * 分页查询
	 * 
	 * @param jpa
	 * @param page
	 * @return
	 */
//	@Deprecated
//	public <T extends BaseEntity> JqDatatablesPageBean toPage(Model model, BaseJpaRepository<T, String> jpa,
//			JqDatatablesPageBean page, Sort sort) {
//
//		logger.debug("start = {}, size = {}", page.getStart(), page.getLength());
//
//		Page<T> listPage = null;
//		if (AccountRoleEnum.ADMIN.getCode().equals(currentManager().getRolePower())) {
//			listPage = jpa.findAll(PageRequest.of(page.getStart() / page.getLength(), page.getLength(), sort));
//		} else {
//			listPage = jpa.findAllByMasterCode(currentManager().getMasterCode(),
//					PageRequest.of(page.getStart() / page.getLength(), page.getLength(), sort));
//		}
//
//		JqDatatablesPageBean p = new JqDatatablesPageBean();
//		p.setData(listPage.getContent());
//		p.setDraw(page.getDraw());
//		p.setRecordsFiltered((int) listPage.getTotalElements());
//		p.setRecordsTotal((int) listPage.getTotalElements());
//
//		return p;
//	}

	@SuppressWarnings("serial")
	public <T extends BaseEntity> JqDatatablesPageBean toPage(Model model, Specification<T> specification,
			BaseJpaRepository<T, String> jpa, JqDatatablesPageBean page, Sort sort) {
		Page<T> listPage = null;

		logger.debug("current manager = {}", ToStringBuilder.reflectionToString(currentManager()));
		Specification<T> filterSpec = specification ; 
		List<MasterMachineEntity> schools = new ArrayList<MasterMachineEntity>() ; 
		
		if (!AccountRoleEnum.ADMIN.getCode().equals(currentManager().getRolePower())) {

			filterSpec = new Specification<T>() {
				@Override
				public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
					List<Predicate> predicates = new ArrayList<Predicate>();

					Predicate condition = criteriaBuilder.equal(root.get("masterCode"), currentManager().getMasterCode());
					Predicate c = specification.toPredicate(root, query, criteriaBuilder);

					predicates.add(condition);
					predicates.add(c);

					return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
				}
			};
			
			schools = masterMachineRepository.findAll() ; 
		}else {
			schools = masterMachineRepository.findAllByMasterCode(currentManager().getMasterCode()) ; 
		}

		model.addAttribute("schools", schools) ; 
		listPage = jpa.findAll(filterSpec, PageRequest.of(page.getStart() / page.getLength(), page.getLength(), sort));

		JqDatatablesPageBean p = new JqDatatablesPageBean();
		p.setData(listPage.getContent());
		p.setDraw(page.getDraw());
		p.setRecordsFiltered((int) listPage.getTotalElements());
		p.setRecordsTotal((int) listPage.getTotalElements());

		return p;
	}

	public <T extends BaseEntity> JqDatatablesPageBean toPage(Model model, Specification<T> specification,
			BaseJpaRepository<T, String> jpa, JqDatatablesPageBean page) {
		Sort sort = Sort.by(Direction.DESC, "addTime");
		return toPage(model, specification, jpa, page, sort);
	}
	

	/**
	 * 生成导出数据
	 * @param model
	 * @param buildFilter
	 * @param jpa
	 * @param page
	 * @param sort
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "serial", "rawtypes" })
	public <T> List<T> toExport(Model model, Specification buildFilter, BaseJpaRepository<T, String> jpa , JqDatatablesPageBean page , Sort sort) {
		List<T> listPage = null;

		logger.debug("current manager = {}", ToStringBuilder.reflectionToString(currentManager()));
		Specification<T> filterSpec = buildFilter ; 
		List<MasterMachineEntity> schools = new ArrayList<MasterMachineEntity>() ; 
		
		if (!AccountRoleEnum.ADMIN.getCode().equals(currentManager().getRolePower())) {

			filterSpec = new Specification<T>() {
				@Override
				public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
					List<Predicate> predicates = new ArrayList<Predicate>();

					Predicate condition = criteriaBuilder.equal(root.get("masterCode"), currentManager().getMasterCode());
					Predicate c = buildFilter.toPredicate(root, query, criteriaBuilder);

					predicates.add(condition);
					predicates.add(c);

					return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
				}
			};
			
			schools = masterMachineRepository.findAll() ; 
		}else {
			schools = masterMachineRepository.findAllByMasterCode(currentManager().getMasterCode()) ; 
		}

		model.addAttribute("schools", schools) ; 
		listPage = jpa.findAll(filterSpec) ; 

		return listPage ;
	}

//	protected <T extends BaseEntity> JqDatatablesPageBean toPage(Model model, BaseJpaRepository<T, String> jpa,
//			JqDatatablesPageBean page) {
//		Sort sort = Sort.by(Direction.DESC, "addTime");
//		return this.toPage(model, jpa, page, sort);
//	}

}
